Skip to content

fix(features): lazy package imports so one broken module can't sink the rest (#10)#35

Open
bradsmithmba wants to merge 1 commit into
cloudtrainerwork:masterfrom
bradsmithmba:fix/features-lazy-init
Open

fix(features): lazy package imports so one broken module can't sink the rest (#10)#35
bradsmithmba wants to merge 1 commit into
cloudtrainerwork:masterfrom
bradsmithmba:fix/features-lazy-init

Conversation

@bradsmithmba

Copy link
Copy Markdown

Summary

src/features/__init__.py eagerly imported FeatureEngineering (from base.py) and the regime feature classes (from regime_features.py) at package import time. base.py imports the data layer (from ..data import get_default_provider, CacheManager, MarketDataRequest), so that one broken import took down the entire package: importing the self-contained modules — greeks, pnl, position_models, position_state, position_vector — failed even though none of them depend on base or data.

Closes #10.

Dependency map

module depends on base/data?
base yes (imports the data layer)
regime_features yes (imports from base)
greeks, pnl, position_models, position_state, position_vector no — self-contained

Under the eager __init__, the five clean modules were unreachable because of the two that aren't.

Fix

Switch __init__ to PEP 562 lazy attribute loading (__getattr__). The public API is unchanged — from src.features import FeatureEngineering still works, importing base on first access — but importing the package or any clean submodule no longer triggers base's dependency chain.

Verification (with the data layer still absent, i.e. before #1)

import src.features                  -> OK; base NOT eagerly loaded
import src.features.greeks           -> OK (previously failed)
import src.features.position_models  -> OK
from src.features import FeatureEngineering -> still needs #1 (lazy, by design)
src.features.UnknownName             -> AttributeError

Adds tests/features/test_lazy_init.py (3 tests) pinning the laziness.

Relationship to #1

Complementary, not overlapping. #1 (PR #19) fixes the missing data layer at the root; this PR contains the blast radius so a broken module in src.features can't sink unrelated ones. They touch different files and merge independently.

🤖 Generated with Claude Code

…he rest

src/features/__init__.py eagerly imported FeatureEngineering (from base.py)
and the regime feature classes. base.py imports the data layer, so the
single broken import took down the entire package: importing the
self-contained modules (greeks, pnl, position_models, position_state,
position_vector) failed even though none of them depend on base or data.

Switch __init__ to PEP 562 lazy attribute loading. The public API is
unchanged (`from src.features import FeatureEngineering` still works, loading
base on first access), but importing the package or any clean submodule no
longer triggers base's dependency chain.

Verified: `import src.features.greeks` now succeeds with the data layer
still absent; base is not loaded until FeatureEngineering/RegimeStateVector
is actually accessed. Adds regression tests.

This is complementary to cloudtrainerwork#1 (which fixes the missing data layer at the
root); it contains the blast radius regardless.

Closes cloudtrainerwork#10

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

src/features/__init__.py eager import causes entire features package to fail when any one module is broken

1 participant